package xin.yangshuai.transactional01.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.transaction.support.DefaultTransactionStatus;
import xin.yangshuai.transactional01.dao.TestUserMapper;
import xin.yangshuai.transactional01.model.TestUser;
import xin.yangshuai.transactional01.service.PropagationServiceA;
import xin.yangshuai.transactional01.service.PropagationServiceB;

@Service
public class PropagationServiceAImpl implements PropagationServiceA {

    @Autowired
    private TestUserMapper testUserMapper;

    @Autowired
    private PropagationServiceB propagationServiceB;

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void requiredToRequired() {
        update1();
        propagationServiceB.required();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void requiredToRequired1() {
        update1();
        try {
            propagationServiceB.required();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void requiredToRequired2() {
        update1();
        propagationServiceB.required1();
        int i = 1 / 0;
    }

    @Override
    public void noToRequired() {
        update1();
        propagationServiceB.required();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void requiredToSupports() {
        update1();
        propagationServiceB.supports();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void requiredToSupports1() {
        update1();
        try {
            propagationServiceB.supports();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void requiredToSupports2() {
        update1();
        propagationServiceB.supports1();
        int i = 1 / 0;
    }

    @Override
    public void noToSupports() {
        update1();
        propagationServiceB.supports();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void requiredToMandatory() {
        update1();
        propagationServiceB.mandatory();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void requiredToMandatory1() {
        update1();
        try {
            propagationServiceB.mandatory();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void requiredToMandatory2() {
        update1();
        propagationServiceB.mandatory1();
        int i = 1 / 0;
    }

    @Override
    public void noToMandatory() {
        update1();
        propagationServiceB.mandatory();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void requiredToRequiresNew() {
        update1();
        propagationServiceB.requiresNew();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void requiredToRequiresNew1() {
        update1();
        try {
            propagationServiceB.requiresNew();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void requiredToRequiresNew2() {
        update1();
        propagationServiceB.requiresNew1();
        int i = 1 / 0;
    }

    @Override
    public void noToRequiresNew() {
        update1();
        propagationServiceB.requiresNew();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void requiredToNotSupported() {
        update1();
        propagationServiceB.notSupported();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void requiredToNotSupported1() {
        update1();
        try {
            propagationServiceB.notSupported();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void requiredToNotSupported2() {
        update1();
        propagationServiceB.notSupported1();
        int i = 1 / 0;
    }


    @Override
    public void noToNotSupported() {
        update1();
        propagationServiceB.notSupported();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void requiredToNever() {
        update1();
        propagationServiceB.never();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void requiredToNever1() {
        update1();
        try {
            propagationServiceB.never();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void requiredToNever2() {
        update1();
        propagationServiceB.never1();
        int i = 1 / 0;
    }

    @Override
    public void noToNever() {
        update1();
        propagationServiceB.never();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void requiredToNested() {
        update1();
        propagationServiceB.nested();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void requiredToNested1() {
        update1();
        try {
            propagationServiceB.nested();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void requiredToNested2() {
        update1();
        propagationServiceB.nested1();
        int i = 1 / 0;
    }

    @Override
    public void noToNested() {
        update1();
        propagationServiceB.nested();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void requiredToNo() {
        update1();
        propagationServiceB.no();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void requiredToNo1() {
        update1();
        try {
            propagationServiceB.no();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void requiredToNo2() {
        update1();
        propagationServiceB.no1();
        int i = 1 / 0;
    }

    @Override
    public void noToNo() {
        update1();
        propagationServiceB.no();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void requiredToRequired3() {
        update1();
        try {
            propagationServiceB.required();
        } catch (Exception e) {
            e.printStackTrace();
        }

        TransactionStatus transactionStatus = TransactionAspectSupport.currentTransactionStatus();
        transactionStatusInfo(transactionStatus);

        // 设置回滚
//        transactionStatus.setRollbackOnly();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void requiredToRequiresNew3() {
        update1();
        try {
            propagationServiceB.requiresNew();
        } catch (Exception e) {
            e.printStackTrace();
        }

        TransactionStatus transactionStatus = TransactionAspectSupport.currentTransactionStatus();
        transactionStatusInfo(transactionStatus);

        // 设置回滚
//        transactionStatus.setRollbackOnly();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void requiredToNested3() {
        update1();
        try {
            propagationServiceB.nested();
        } catch (Exception e) {
            e.printStackTrace();
        }

        TransactionStatus transactionStatus = TransactionAspectSupport.currentTransactionStatus();
        transactionStatusInfo(transactionStatus);

        // 设置回滚
//        transactionStatus.setRollbackOnly();
    }

    private void update1() {
        TestUser testUser1 = new TestUser();
        testUser1.setId(1);
        testUser1.setName("aa");
        testUser1.setAge(15);
        testUserMapper.updateByPrimaryKey(testUser1);
        System.out.println("update testUser1");
    }

    private void update2() {
        TestUser testUser2 = new TestUser();
        testUser2.setId(2);
        testUser2.setName("bb");
        testUser2.setAge(25);
        testUserMapper.updateByPrimaryKey(testUser2);
        System.out.println("update testUser2");
    }

    private void transactionStatusInfo(TransactionStatus transactionStatus) {
        if (transactionStatus instanceof DefaultTransactionStatus) {
            DefaultTransactionStatus defaultTransactionStatus = (DefaultTransactionStatus) transactionStatus;
            System.out.println(defaultTransactionStatus.toString());

            System.out.println("isGlobalRollbackOnly: " + defaultTransactionStatus.isGlobalRollbackOnly());
            System.out.println("isLocalRollbackOnly: " + defaultTransactionStatus.isLocalRollbackOnly());
            System.out.println("isRollbackOnly: " + defaultTransactionStatus.isRollbackOnly());
            System.out.println("hasSavepoint: " + defaultTransactionStatus.hasSavepoint());
        }
    }
}
